package com.koushikdutta.async.http.server;

import android.text.TextUtils;
import com.koushikdutta.async.AsyncSocket;
import com.koushikdutta.async.BufferedDataSink;
import com.koushikdutta.async.ByteBufferList;
import com.koushikdutta.async.DataSink;
import com.koushikdutta.async.Util;
import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.WritableCallback;
import com.koushikdutta.async.http.HttpUtil;
import com.koushikdutta.async.http.filter.ChunkedOutputFilter;
import com.koushikdutta.async.http.libcore.RawHeaders;
import com.koushikdutta.async.http.libcore.ResponseHeaders;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;

public class AsyncHttpServerResponseImpl implements AsyncHttpServerResponse {
    static final /* synthetic */ boolean $assertionsDisabled = (!AsyncHttpServerResponseImpl.class.desiredAssertionStatus());
    private long mContentLength = -1;
    boolean mEnded;
    boolean mHasWritten = false;
    private boolean mHeadWritten = false;
    private ResponseHeaders mHeaders = new ResponseHeaders(null, this.mRawHeaders);
    private RawHeaders mRawHeaders = new RawHeaders();
    AsyncHttpServerRequestImpl mRequest;
    DataSink mSink;
    AsyncSocket mSocket;

    public ResponseHeaders getHeaders() {
        return this.mHeaders;
    }

    AsyncHttpServerResponseImpl(AsyncSocket socket, AsyncHttpServerRequestImpl req) {
        this.mSocket = socket;
        this.mRequest = req;
        if (HttpUtil.isKeepAlive(req.getHeaders().getHeaders())) {
            this.mRawHeaders.set("Connection", "Keep-Alive");
        }
    }

    public void write(ByteBuffer bb) {
        if (bb.remaining() != 0) {
            writeInternal(bb);
        }
    }

    public void write(ByteBufferList bb) {
        if (bb.remaining() != 0) {
            writeInternal(bb);
        }
    }

    private void writeInternal(ByteBuffer bb) {
        if (!$assertionsDisabled && this.mEnded) {
            throw new AssertionError();
        } else if (this.mHasWritten) {
            this.mSink.write(bb);
        } else {
            initFirstWrite();
        }
    }

    private void writeInternal(ByteBufferList bb) {
        if (!$assertionsDisabled && this.mEnded) {
            throw new AssertionError();
        } else if (this.mHasWritten) {
            this.mSink.write(bb);
        } else {
            initFirstWrite();
        }
    }

    void initFirstWrite() {
        boolean canUseChunked = true;
        if (!this.mHasWritten) {
            this.mHasWritten = true;
            if ($assertionsDisabled || this.mRawHeaders.getStatusLine() != null) {
                String currentEncoding = this.mRawHeaders.get("Transfer-Encoding");
                if ("".equals(currentEncoding)) {
                    this.mRawHeaders.removeAll("Transfer-Encoding");
                }
                if (!("Chunked".equalsIgnoreCase(currentEncoding) || currentEncoding == null) || "close".equalsIgnoreCase(this.mRawHeaders.get("Connection"))) {
                    canUseChunked = false;
                }
                if (this.mContentLength < 0) {
                    String contentLength = this.mRawHeaders.get("Content-Length");
                    if (!TextUtils.isEmpty(contentLength)) {
                        this.mContentLength = Long.valueOf(contentLength).longValue();
                    }
                }
                if (this.mContentLength >= 0 || !canUseChunked) {
                    this.mSink = this.mSocket;
                } else {
                    this.mRawHeaders.set("Transfer-Encoding", "Chunked");
                    this.mSink = new ChunkedOutputFilter(this.mSocket);
                }
                writeHeadInternal();
                return;
            }
            throw new AssertionError();
        }
    }

    public void setWriteableCallback(WritableCallback handler) {
        initFirstWrite();
        this.mSink.setWriteableCallback(handler);
    }

    public WritableCallback getWriteableCallback() {
        initFirstWrite();
        return this.mSink.getWriteableCallback();
    }

    public void end() {
        if ("Chunked".equalsIgnoreCase(this.mRawHeaders.get("Transfer-Encoding"))) {
            initFirstWrite();
            ((ChunkedOutputFilter) this.mSink).setMaxBuffer(Integer.MAX_VALUE);
            this.mSink.write(new ByteBufferList());
            onEnd();
        } else if (!this.mHasWritten) {
            if (this.mRequest.getMethod().equalsIgnoreCase("HEAD")) {
                writeHead();
                onEnd();
                return;
            }
            send("text/html", "");
        }
    }

    public void writeHead() {
        initFirstWrite();
    }

    private void writeHeadInternal() {
        if ($assertionsDisabled || !this.mHeadWritten) {
            this.mHeadWritten = true;
            Util.writeAll(this.mSocket, this.mRawHeaders.toHeaderString().getBytes(), new CompletedCallback() {
                public void onCompleted(Exception ex) {
                    if (AsyncHttpServerResponseImpl.this.mSink instanceof BufferedDataSink) {
                        ((BufferedDataSink) AsyncHttpServerResponseImpl.this.mSink).setDataSink(AsyncHttpServerResponseImpl.this.mSocket);
                    }
                    WritableCallback writableCallback = AsyncHttpServerResponseImpl.this.getWriteableCallback();
                    if (writableCallback != null) {
                        writableCallback.onWriteable();
                    }
                }
            });
            return;
        }
        throw new AssertionError();
    }

    public void send(String contentType, String string) {
        try {
            if (this.mRawHeaders.getStatusLine() == null) {
                responseCode(200);
            }
            if ($assertionsDisabled || this.mContentLength < 0) {
                byte[] bytes = string.getBytes("UTF-8");
                this.mContentLength = (long) bytes.length;
                this.mRawHeaders.set("Content-Length", Integer.toString(bytes.length));
                this.mRawHeaders.set("Content-Type", contentType);
                Util.writeAll((DataSink) this, string.getBytes(), new CompletedCallback() {
                    public void onCompleted(Exception ex) {
                        AsyncHttpServerResponseImpl.this.onEnd();
                    }
                });
                return;
            }
            throw new AssertionError();
        } catch (UnsupportedEncodingException e) {
            if (!$assertionsDisabled) {
                throw new AssertionError();
            }
        }
    }

    protected void onEnd() {
        this.mEnded = true;
    }

    public void responseCode(int code) {
        String status = AsyncHttpServer.getResponseCodeDescription(code);
        this.mRawHeaders.setStatusLine(String.format("HTTP/1.1 %d %s", new Object[]{Integer.valueOf(code), status}));
    }

    public void onCompleted(Exception ex) {
        end();
    }

    public boolean isOpen() {
        if (this.mSink != null) {
            return this.mSink.isOpen();
        }
        return this.mSocket.isOpen();
    }

    public void setClosedCallback(CompletedCallback handler) {
        this.mSink.setClosedCallback(handler);
    }
}
